﻿<%@ WebHandler Language="C#" Class="CAPTCHAImageHandler" %>

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Web.Security;
using System.Security.Cryptography;
using System.IO;
using System.Text;
using System.Web;
using System.Web.SessionState;

public class CAPTCHAImageHandler : IHttpHandler, IReadOnlySessionState
{
    
    public void ProcessRequest (HttpContext context) 
    {
        context.Response.Clear();

        // Create a CAPTCHA image using the text stored in the Session object.
        if (context.Session[CE.Global.General.SecurityCheckWord] != null)
        {
            //string _securityWord = context.Session[CE.Global.General.SecurityCheckWord].ToString();
            CaptchaImage.CaptchaImage ci = new CaptchaImage.CaptchaImage(context.Session[CE.Global.General.SecurityCheckWord].ToString(), 170, 40, "Century Schoolbook");

            // Change the response headers to output a JPEG image.
            context.Response.Clear();
            context.Response.ContentType = "image/jpeg";

            // Write the image to the response stream in JPEG format.
            ci.Image.Save(context.Response.OutputStream, ImageFormat.Jpeg);

            // Dispose of the CAPTCHA image object.
            ci.Dispose();
        }
    }
 
    public bool IsReusable {
        get {
            return false;
        }
    }

    private void GetCAPTCHAImage(string salt)
    {

        return;
    }

    private Image GetImage(string salt)
    {
        // Not sure how you are building your MemoryStream
        // Once you have it, you just use the Image class to 
        // create the image from the stream.
        int width = Convert.ToInt32(salt.Length * 20) + 25;
        int height = 80;
        int fontsize = 25;

        if (salt.Length > 5 && salt.Length < 10)
        {
            width -= 55;
            //fontsize = 18;
        }
        if (salt.Length >= 10)
        {
            width -= 30;
            //fontsize = 20;
            height = 60;
        }
        else
        {
            width += 80;
        }

        int orgWidth = width;


        float fw = Convert.ToSingle(width * (0.12 * (salt.Length - 1)));
        width = Convert.ToInt32(fw) + 20;

        MemoryStream stream = new MemoryStream();
        Random r = new Random();
        Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
        Graphics g = Graphics.FromImage(bmp);
        g.TextRenderingHint = TextRenderingHint.AntiAlias;
        g.Clear(Color.White);
        g.DrawRectangle(Pens.LightGray, 1, 1, width - 3, height - 3);
        //g.DrawRectangle(Pens.Gray, 0, 0, width, height);
        System.Drawing.Drawing2D.Matrix mymat = new System.Drawing.Drawing2D.Matrix();
        float _totdec = 0.0f;
        for (int i = 0; i < salt.Length; i++)
        {
            mymat.Reset();
            float w = Convert.ToSingle(orgWidth * (0.1 * i));
            float h = Convert.ToSingle(height - 10);
            if (i > 1)
            {
                if (salt[i - 1].ToString().ToLower() == "i" || salt[i - 1].ToString().ToLower() == "l" || salt[i - 1].ToString().ToLower() == "t")
                {
                    w -= 7f;
                    _totdec += 7f;
                }
                else
                {
                    w -= _totdec;
                }
            }

            if (i == 1)
            {
                if (salt[i - 1].ToString().ToLower() == "w" || salt[i - 1].ToString().ToLower() == "m")
                {
                    w += 6f;
                    _totdec -= 6f;
                }
                else if (salt[i - 1].ToString().ToLower() == "h" || salt[i - 1].ToString().ToLower() == "q")
                {
                    w += 5f;
                    _totdec -= 5f;
                }
                else
                {
                    w += 3f;
                    _totdec -= 4f;
                }
            }

            //mymat.RotateAt(r.Next(-10, 0), new PointF(w, h * 0.5f));

            g.Transform = mymat;
            g.DrawString(salt[i].ToString(), new Font("Comic Sans MS", fontsize, FontStyle.Bold), Brushes.Black, w, h * 0.3f);
            //if (i > 0)
            //{
            //    if (salt[i - 1].ToString().ToLower() == "i" || salt[i].ToString().ToLower() == "l" || salt[i].ToString().ToLower() == "t")
            //    {
            //        g.DrawString(salt[i].ToString(), new Font("Comic Sans MS", fontsize, FontStyle.Bold), Brushes.Black, w - 10f, h * 0.3f);
            //    }
            //    else
            //    {
            //        g.DrawString(salt[i].ToString(), new Font("Comic Sans MS", fontsize, FontStyle.Bold), Brushes.Black, w, h * 0.3f);
            //    }
            //}
            //else
            //{
            //    g.DrawString(salt[i].ToString(), new Font("Comic Sans MS", fontsize, FontStyle.Bold), Brushes.Black, w, h * 0.3f);
            //}

            g.ResetTransform();
        }
        AddNoise(g, width, height);
        bmp.Save(stream, ImageFormat.Jpeg);

        //bmp.Save(Path, ImageFormat.Gif);
        g.Dispose();
        bmp.Dispose();

        return Image.FromStream(stream);
    }

    private void AddNoise(Graphics g, int width, int height)
    {
        int density = 50;
        int size = 40;
        SolidBrush br = new SolidBrush(Color.Black);
        Random _ramdom = new Random();
        int max = Convert.ToInt32(Math.Max(width - 3, height - 3) / size);
        for (int i = 0; i <= Convert.ToInt32(((width - 3) * (height - 3)) / density); i++)
        {
            g.FillEllipse(br, _ramdom.Next(width - 3), _ramdom.Next(height - 3), _ramdom.Next(max), _ramdom.Next(max));
            g.FillRectangle(br, _ramdom.Next(width - 3), _ramdom.Next(height - 3), _ramdom.Next(max), _ramdom.Next(max));
            if (i % 10 == 0)
            {
                g.DrawLine(new Pen(br, 1.2f), new Point(_ramdom.Next(width - 3), _ramdom.Next(height - 3)), new Point(_ramdom.Next(width - 3), _ramdom.Next(height - 3)));
            }
        }
        br.Dispose();
    }

}